package ca.cbc.medialib.service;

import ca.cbc.medialib.entity.Category;

import org.hibernate.Hibernate;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import ca.cbc.medialib.entity.FailedMedia;
import ca.cbc.medialib.entity.Media;
import ca.cbc.medialib.entity.Sponsor;
import ca.cbc.medialib.exception.ThePlatformObjectNotFoundException;
import ca.cbc.medialib.util.HibernateUtil;
import org.dbunit.DatabaseUnitException;
import org.dbunit.database.DatabaseConnection;
import org.dbunit.database.IDatabaseConnection;
import org.dbunit.operation.DatabaseOperation;
import org.hamcrest.Matchers;
import org.hamcrest.core.IsNull;
import org.hibernate.cfg.AnnotationConfiguration;
import org.hibernate.classic.Session;
import org.hibernate.tool.hbm2ddl.SchemaExport;
import org.junit.After;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;

import java.sql.SQLException;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

import static org.hamcrest.MatcherAssert.*;
import static org.hamcrest.Matchers.*;
import static org.junit.matchers.JUnitMatchers.hasItem;

/**
 * Created by IntelliJ IDEA.
 * User: arash
 * Date: 11-06-27
 * Time: 3:34 PM
 * To change this template use File | Settings | File Templates.
 */
public class MediaStorageServiceImplTestWrite {
    // initialize your database connection here
    private IDatabaseConnection connection = null;

    @After
    public void after() {
        HibernateUtil.shutdown();
    }

    @Test
    @Ignore
    public void sandBox() {
        AnnotationConfiguration cfg = new AnnotationConfiguration().configure();
        SessionFactory sf = cfg.buildSessionFactory();
        new SchemaExport(cfg).create(true, false);
    }

    @Before
    public void before() {
        try {
            HibernateUtil.beginTransaction();
            connection = new DatabaseConnection(HibernateUtil.getSession().connection());
            // initialize your dataset here
            DatabaseOperation.CLEAN_INSERT.execute(connection, DbUnitTestUtil.getDataSet());

            HibernateUtil.commitTransaction();
        } catch (SQLException e) {
            e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
        } catch (DatabaseUnitException e) {
            e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
        } catch (Exception e) {
            e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
        } finally {

        }
    }


    @Test
    public void testMergeCategory() {
        Category cat = new Category(909, "test1 category", "testing the insertion of category", "blah blah blah",
                "http://bigbox.com", "http://banner.com", "http://banner.com", "http://thunbernail.com");
        Sponsor sponsor1 = new Sponsor("http://sponsorImageUrl909090", "http://sponsorlink909090");
        Sponsor sponsor2 = new Sponsor("http://sponsorImageUrl909092", "http://sponsorlink909092");
        Sponsor sponsor3 = new Sponsor("http://sponsorImageUrl909093", "http://sponsorlink909093");
        cat.addSponsor(sponsor1);
        cat.addSponsor(sponsor2);
        cat.addSponsor(sponsor3);

        MediaStorageServiceImpl mss = new MediaStorageServiceImpl();
        //Save category first
        HibernateUtil.beginTransaction();
        mss.saveCategory(cat);
        HibernateUtil.commitTransaction();

        //change something and merge it
        sponsor3.setImageUrl("http://updated");
        HibernateUtil.beginTransaction();
        mss.mergeCategory(cat);
        HibernateUtil.commitTransaction();

        //fetch if from DB
        HibernateUtil.beginTransaction();
        Category category = mss.getCategory(909);

        assertThat("merge category test", category.getSponsors(), hasItem(Matchers.<Sponsor>hasProperty("imageUrl", is("http://updated"))));
        HibernateUtil.commitTransaction();
    }

    @Test
    public void testCreateCategory() {
        Category cat = new Category(909, "test1 category", "testing the insertion of category", "blah blah blah",
                "http://bigbox.com", "http://banner.com"," http://banner.com", "http://thunbernail.com");
        Sponsor sponsor1 = new Sponsor("http://sponsorImageUrl909090", "http://sponsorlink909090", cat);
        Sponsor sponsor2 = new Sponsor("http://sponsorImageUrl909092", "http://sponsorlink909092", cat);
        Sponsor sponsor3 = new Sponsor("http://sponsorImageUrl909093", "http://sponsorlink909093", cat);
        cat.addSponsor(sponsor1);
        cat.addSponsor(sponsor2);
        cat.addSponsor(sponsor3);

        Category cat2 = new Category(909, "test category", "testing the insertion of category", "blah blah blah",
                "http://bigbox.com", "http://banner.com", "http://banner.com", "http://thunbernail.com");
        Sponsor sponsor4 = new Sponsor("http://sponsorImageUrl909090", "http://sponsorlink909090", cat2);
        Sponsor sponsor5 = new Sponsor("http://sponsorImageUrl909092", "http://sponsorlink909092", cat2);
        Sponsor sponsor6 = new Sponsor("http://sponsorImageUrl909093", "http://sponsorlink909095", cat2);
        cat2.addSponsor(sponsor4);
        cat2.addSponsor(sponsor5);
        cat2.addSponsor(sponsor6);
        MediaStorageService mss = new MediaStorageServiceImpl();
        HibernateUtil.beginTransaction();
        mss.saveCategory(cat);
        HibernateUtil.commitTransaction();

        HibernateUtil.beginTransaction();
        mss.saveCategory(cat2);
        HibernateUtil.commitTransaction();

        HibernateUtil.beginTransaction();
        Category newCat = mss.getCategory(909);
        assertThat("number of sponsors", newCat.getSponsors().size(), equalTo(3));
        assertThat("title", newCat.getTitle(), equalTo("test category"));
        assertThat("full title ", newCat.getFullTitle(), equalTo("testing the insertion of category"));
        assertThat("desription   ", newCat.getDescription(), equalTo("blah blah blah"));
        assertThat("sponsor 1", newCat.getSponsors(), hasItem(Matchers.<Sponsor>hasProperty("imageUrl", is("http://sponsorImageUrl909090"))));
        assertThat("sponsor 1", newCat.getSponsors(), hasItem(Matchers.<Sponsor>hasProperty("imageUrl", is("http://sponsorImageUrl909092"))));
        assertThat("sponsor 1", newCat.getSponsors(), hasItem(Matchers.<Sponsor>hasProperty("imageUrl", is("http://sponsorImageUrl909093"))));
        assertThat("sponsor 1", newCat.getSponsors(), not(hasItem(Matchers.<Sponsor>hasProperty("url", is("http://sponsorlink909093")))));
        assertThat("sponsor 1", newCat.getSponsors(), hasItem(Matchers.<Sponsor>hasProperty("url", is("http://sponsorlink909095"))));
        HibernateUtil.commitTransaction();
    }

    @Test
    public void testGetCategory() {
        HibernateUtil.getSession().beginTransaction();
        MediaStorageService mss = new MediaStorageServiceImpl();
        Category cat = mss.getCategory(112);
        assertThat("title ", cat.getTitle(), equalTo("Season 2"));
        assertThat("full title ", cat.getFullTitle(), equalTo("/show/Being Erica/Season 2"));
        assertThat("Big box ", cat.getBigBoxUrl(), equalTo("http://bigbox.com"));
        assertThat("Banner URl ", cat.getBannerAdUrl(), equalTo("http://banner.com"));
        assertThat("sponsors", cat.getSponsors(), hasItem(Matchers.<Sponsor>hasProperty("url", is("http://sponsorlink1"))));
        assertThat("sponsors", cat.getSponsors(), hasItem(Matchers.<Sponsor>hasProperty("url", is("http://sponsorlink2"))));
        assertThat("sponsors", cat.getSponsors(), hasItem(Matchers.<Sponsor>hasProperty("url", is("http://sponsorlink3"))));
        HibernateUtil.getSession().getTransaction().commit();
    }

    @Test
    public void testDelete() {
        HibernateUtil.getSession().beginTransaction();
        MediaStorageService mss = new MediaStorageServiceImpl();
        mss.delete(mss.getCategory(112));
        //testing the null branch
        mss.delete(null);
        HibernateUtil.getSession().getTransaction().commit();
        Session session = HibernateUtil.getSession();
        session.beginTransaction();

        Category cat = mss.getCategory(112);
        assertThat("Category is not deleted ", cat, Matchers.<Object>nullValue());
        //the sponsors should be deleted as well

        HibernateUtil.getSession().getTransaction().commit();


    }

    @Test
    public void testDeleteMedia() {
        HibernateUtil.getSession().beginTransaction();
        MediaStorageService mss = new MediaStorageServiceImpl();
        Media m = mss.getMediaByReleaseId(1L);
        mss.delete(m);
        HibernateUtil.commitTransaction();
        HibernateUtil.beginTransaction();
        Category cat = mss.getCategory(12L);
        assertThat(cat, nullValue());
        Category cat1 = mss.getCategory(11L);
        assertThat(cat1, notNullValue());
        HibernateUtil.commitTransaction();
    }

    @Test
    public void testSaveFailedMedia() {
        HibernateUtil.beginTransaction();
        MediaStorageService mss = new MediaStorageServiceImpl();
        Date date = new Date();
        FailedMedia fm = new FailedMedia(909090, 909091, 909092, "Failed Media", "Failed media release url", date);
        mss.saveFailedMedia(fm);
        HibernateUtil.commitTransaction();
        HibernateUtil.beginTransaction();
        List<FailedMedia> fm1 = mss.listFailedMedia();
        assertThat("failed media saved", fm1, hasItem(Matchers.<FailedMedia>hasProperty("releaseId", is(909090L))));
        assertThat("failed media saved", fm1, hasItem(Matchers.<FailedMedia>hasProperty("title", is("Failed Media"))));
        HibernateUtil.commitTransaction();
    }

    @Test
    public void testSaveCategoryFromThePlatform() {
        CategoryService cs = new CategoryService();
        try {
            Category c = cs.get(1196578276);
            HibernateUtil.beginTransaction();
            MediaStorageService mss = new MediaStorageServiceImpl();
            mss.saveCategory(c);
            HibernateUtil.commitTransaction();
            HibernateUtil.getSession().close();
            HibernateUtil.beginTransaction();
            MediaStorageService mss1 = new MediaStorageServiceImpl();
            Category c1 = mss1.getCategory(1196578276);
            assertThat(c1.getTitle(), equalTo("DEV - 18 to Life"));
            assertThat(c1.getFullTitle(), equalTo("Shows/DEV - 18 to Life"));
            c1 = c1.getParent();
            assertThat(c1.getParent(), IsNull.<Object>nullValue());
            assertThat(c1.getTitle(), equalTo("Shows"));
            assertThat(c1.getFullTitle(), equalTo("Shows"));


        } catch (ThePlatformObjectNotFoundException e) {
            e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
        }
    }

    @Test
    public void testSaveCategoriesWithSharedParent() {
        Category parent = new Category(9898981, "parent", "Shared Parent", null, null, null, null, null);
        Category c1 = new Category(9898982, "child first", "Shared Parent/Child1", null, null, null, null, null);
        Category c2 = new Category(9898983, "child second", "Shared Parent/Child2", null, null, null, null, null);
        c1.setParent(parent);
        c2.setParent(parent);
        HibernateUtil.beginTransaction();
        MediaStorageService mss = new MediaStorageServiceImpl();
        mss.saveCategory(c1);
        mss.saveCategory(c2);
        HibernateUtil.commitTransaction();
        HibernateUtil.beginTransaction();
        Category c4 = mss.getCategory(9898981);
        assertThat(c4.getFullTitle(), equalTo("Shared Parent"));
        Category secondChild = mss.getCategory(9898983);
        assertThat(secondChild.getFullTitle(), equalTo("Shared Parent/Child2"));

    }

    @Test
    public void testSaveCategoriesWithSharedParentId() {
        Category parent = new Category(9898981, "parent", "Shared Parent", null, null, null, null, null);
        Category parent1 = new Category(9898981, "parent", "Shared Parent", null, null, null, null, null);
        Category c1 = new Category(9898982, "child first", "Shared Parent/Child1", null, null, null, null, null);
        Category c2 = new Category(9898983, "child second", "Shared Parent/Child2", null, null, null, null, null);
        c1.setParent(parent);
        c2.setParent(parent1);
        HibernateUtil.beginTransaction();
        MediaStorageService mss = new MediaStorageServiceImpl();
        mss.saveCategory(c1);
        mss.saveCategory(c2);
        HibernateUtil.commitTransaction();
        HibernateUtil.beginTransaction();
        Category c4 = mss.getCategory(9898981);
        assertThat(c4.getFullTitle(), equalTo("Shared Parent"));
        Category secondChild = mss.getCategory(9898983);
        assertThat(secondChild.getFullTitle(), equalTo("Shared Parent/Child2"));

    }

    @Test
    public void testSaveCategoryWithExistingParent() {
        Category c1 = new Category(9898982, "Child1", "Share/Child1", null, null, null, null, null);
        HibernateUtil.beginTransaction();
        MediaStorageService mss = new MediaStorageServiceImpl();
        Category parent = mss.getCategory(1);
        c1.setParent(parent);
        mss.saveCategory(c1);
        HibernateUtil.commitTransaction();
        HibernateUtil.beginTransaction();
        Category c11 = mss.getCategory(9898982);
        assertThat(c11.getParent().getTitle(), equalTo("show"));
        assertThat(c11.getParent().getFullTitle(), equalTo("/show"));
    }

    @Test
    public void testSaveCategoryParentCascade() throws ThePlatformObjectNotFoundException {
        //get test category from theP
        String fullTitleA = "Matt Parent/Matt Child 1/Matt Child A";
        String fullTitleB = "Matt Parent/Matt Child 1/Matt Child B";
        CategoryService cs = new CategoryService();

        Category catA = cs.findByFullTitle(fullTitleA);
        Category catB = cs.findByFullTitle(fullTitleB);
        MediaStorageService mss = new MediaStorageServiceImpl();

        HibernateUtil.beginTransaction();
        mss.saveCategory(catA);
        mss.saveCategory(catB);
        HibernateUtil.commitTransaction();

        //assert equal
        HibernateUtil.beginTransaction();
        assertThat(mss.getCategoryByFullTitle(fullTitleA).getParent().getTitle(), equalTo("Matt Child 1"));
        assertThat(mss.getCategoryByFullTitle(fullTitleB).getParent().getTitle(), equalTo("Matt Child 1"));
        assertThat(mss.getCategoryByFullTitle(fullTitleA).getParent().getParent().getTitle(), equalTo("Matt Parent"));
        assertThat(mss.getCategoryByFullTitle(fullTitleB).getParent().getParent().getTitle(), equalTo("Matt Parent"));
        HibernateUtil.commitTransaction();
    }

    @Test
    public void saveMediaTest() {
        Date airDate = new Date();
        Date avaDate = airDate;
        Calendar cal = Calendar.getInstance();
        cal.setTime(airDate);
        cal.add(Calendar.YEAR, 2);
        Date expDate = cal.getTime();
        Media media2 = Media.Builder.getBuilder()
                .withAdCategory("AdCategory")
                .withAirDate(airDate)
                .withAudioVideo("video")
                .withAvailableDate(avaDate)
                .withAvailableInMobile("true")
                .withChapterStartTimes("0:15, 1:30")
                .withDelivery("download")
                .withDescription("A test Media Object Two")
                .withEpisodeNumber("22")
                .withGenre("test")
                .withId(2)
                .withKeywords("test1")
                .withLength("00:01:23")
                .withLiveOndemand("on-demand")
                .withMobileExpiryDate(expDate)
                .withMobileId(2)
                .withOriginalFileName("testcase2")
                .withReleaseId(2)
                .withReleaseUrl("http://releaseUrl")
                .withSeasonNumber("2")
                .withShow("testshow")
                .withThumbnailUrl("http://thumbnailUrl")
                .withTitle("test save").buildNew();
        HibernateUtil.beginTransaction();
        Session session = HibernateUtil.getSession();
        Category cat = (Category) session.get(Category.class, 11L);
        media2.addCategory(cat);
        MediaStorageService mss = new MediaStorageServiceImpl();
        mss.saveMedia(media2);
        HibernateUtil.commitTransaction();

        HibernateUtil.beginTransaction();
        session = HibernateUtil.getSession();

        Media m = (Media) session.get(Media.class, 2L);
        assertThat("Media title failed", m.getTitle(), equalTo("test save"));
        assertThat("Media Category did not match", m.getCategories(), hasItem(Matchers.<Category>hasProperty("title", is("Being Erica"))));
        Media m3 = Media.Builder.getBuilder().withId(2).withAdCategory("new ad category").withReleaseId(2).withDelivery("download").withAvailableInMobile("true").buildNew();
        mss.mergeMedia(m3);
        HibernateUtil.commitTransaction();
        HibernateUtil.beginTransaction();
        session = HibernateUtil.getSession();
        Media m1 = mss.getMedia(2L);
        assertThat("Media merge ", m1.getAdCategory(), equalTo("new ad category"));
        HibernateUtil.commitTransaction();
    }

    @Test
    public void deletingMediaShouldRemoveEmptyCategory(){
        HibernateUtil.beginTransaction();
        MediaStorageService ms = new MediaStorageServiceImpl();
        Media m = Media.Builder.getBuilder().withReleaseId(1L).withTitle("Hello").buildNew();
        Media m1 = ms.getMediaByReleaseId(1L);
        System.out.println(m1.getTitle());
        System.out.println(m.getTitle());
        ms.mergeMedia(m);
        HibernateUtil.commitTransaction();
        HibernateUtil.beginTransaction();
        ms = new MediaStorageServiceImpl();

        Media m2 = ms.getMediaByReleaseId(1L);
        Category c = ms.getCategory(12L);
        assertThat(m2.getTitle(), equalTo("Hello"));
        assertThat(c, nullValue());
        HibernateUtil.commitTransaction();

    }
}
